using System;
using Qyoto;
using Clandestine.Engines.Field;
using Shlick.LayerModel;

namespace Shlick
{
	using Object = Clandestine.Engines.Field.Object;
	public delegate void LayerTreeSelectionHandler(LayerTreeItem itemType);
	
	public class LayerTreeView : QTreeView
	{
		public MapDocument MapDocument { get; private set; } 
		public Map Map { get { return this.MapDocument.Map; } } 
		public Object CurrentObject { get; private set; } // the object the current LayerTree is displying, if any.
		public LayerTreeMode Mode { get; private set; }
		public LayerTreeItem SelectedItemType;
		public event LayerTreeSelectionHandler ItemSelected;
		private LayerTreeModel layerModel;
		private Item selectedItem; 
		
		public LayerTreeView(QWidget parent, MapDocument mapDocument, LayerTreeMode mode, bool haveContextMenu, Clandestine.Engines.Field.Object obj) : base(parent)
		{
			this.MapDocument = mapDocument;
			this.Mode = mode;
			this.CurrentObject = obj;
			
			// Create a model
			this.UpdateMode(mode, obj);
			
			// UI stuff
			this.selectionMode = QAbstractItemView.SelectionMode.SingleSelection;
			this.DragEnabled = true;
			this.ShowDropIndicator = true;
			this.AcceptDrops = true;
			this.ContextMenuPolicy = (haveContextMenu) ? ContextMenuPolicy.CustomContextMenu : ContextMenuPolicy.NoContextMenu;
			
			// Events!
			Connect(this, SIGNAL("clicked(QModelIndex)"), this, SLOT("itemClicked(QModelIndex)"));
			Connect(this, SIGNAL("customContextMenuRequested(QPoint)"), this, SLOT("showContextMenu(QPoint)"));
		}
		
		public void BeginChange()
		{
			layerModel.BeginChange();
		}
		
		public void EndChange()
		{
			layerModel.EndChange();
			
			this.ExpandAll(); // :)
			for (int i = 0; i < 4; i++)
				this.ResizeColumnToContents(i);
		}
		
		public void UpdateMode(LayerTreeMode mode)
		{
			UpdateMode(mode, null);
		}	
		public void UpdateMode(LayerTreeMode mode, Object obj)
		{
			this.Mode = mode;
			this.CurrentObject = obj;
			layerModel = new LayerTreeModel(this.MapDocument, mode, obj); // originally this was a local var, but I think it was getting GC'd and smoke wasn't expecting it = sefault.
			this.SetModel(layerModel);
		}
					
		public override void SetModel (QAbstractItemModel model)
		{
			base.SetModel (model);
			
			this.ExpandAll(); // :)
			for (int i = 0; i < 4; i++)
				this.ResizeColumnToContents(i);
		}
		
		[Q_SLOT("showContextMenu(QPoint)")]
		protected void showContextMenu(QPoint pos)
		{
			if (selectedItem != null)
				selectedItem.ContextMenuRequested(this, QCursor.Pos());
		}
		
		[Q_SLOT("itemClicked(QModelIndex)")]
		protected void itemClicked(QModelIndex index)
		{
			this.rememberSelection((Item)index.InternalPointer());
		}
		
		private void rememberSelection(Item i)
		{
			selectedItem = i;
			
			// Whether we update ActiveLayer alone or ActiveLevel too depends on whether we're in Mode.Map or Mode.Object ;)
	       	if (selectedItem is LayerItem)
            	this.MapDocument.ToolManager.ActiveLayer = ((LayerItem)selectedItem).Layer;
			if (this.Mode == LayerTreeMode.Map || this.Mode == LayerTreeMode.Level)
			{
		        if (selectedItem is LayerItem)
                    this.MapDocument.ToolManager.ActiveLevel = ((LevelItem)selectedItem.Parent().Parent()).Level;
                else if (selectedItem is LayerGroupItem)
                    this.MapDocument.ToolManager.ActiveLevel = ((LevelItem)selectedItem.Parent()).Level;
                else if (selectedItem is LevelItem)
                    this.MapDocument.ToolManager.ActiveLevel = ((LevelItem)selectedItem).Level;
               	else if (selectedItem is ObjectListItem)
               		this.MapDocument.ToolManager.ActiveLevel = ((LevelItem)selectedItem.Parent()).Level;
			}
			
			this.raiseSelectionEvent();
		}
		
		private void raiseSelectionEvent()
		{
			// Type?
			if (selectedItem is MapItem)
				SelectedItemType = LayerTreeItem.Map;
			else if (selectedItem is LevelItem)
				SelectedItemType = LayerTreeItem.Level;
			else if (selectedItem is LayerGroupItem)
				SelectedItemType = LayerTreeItem.LayerGroup;
			else if (selectedItem is LayerItem)
				SelectedItemType = LayerTreeItem.Layer;
			else if (selectedItem is ObjectListItem)
				SelectedItemType = LayerTreeItem.ObjectList;
			else if (selectedItem is ObjectItem)
				SelectedItemType = LayerTreeItem.Object;
			else
				throw new NotImplementedException();
				
			// Raise
			if (ItemSelected != null)
				ItemSelected(SelectedItemType);
		}
	}
}

